module Input.GamePad;

public const int JOYAXIS_X = 0;
public const int JOYAXIS_Y = 1;
public const int JOYAXIS_Z = 2;


public interface IGamePad{
	 int x();
	 int y();
	 void x( int xx );
	 void y( int yy );
	 int xMove();
	 int yMove();

	 int  getButton( int n );
	 void setButton( int n  , int val );
	 ButtonStatus[]  buttonStatus();

	 int  padStatus();
	 void padStatus( int st );
	 void reset();
} //

public class ButtonStatus{
	private bool _pushed    = false;
	private bool _released  = false;
	private bool _changed   = false;
	private int  _lastValue = 0;
	
	public this(){
		reset();
	} //

	public bool changed(){
		return _changed;
	} //

	public bool pushed(){
		return _pushed;
	} //

	public bool released(){
		return _released;
	} //

	public void reset(){
		_pushed   = false;
		_released = false;
		_changed  = false;
		_lastValue= 0;
	} //

	public void copyFrom( ButtonStatus st ){
		_pushed    = st._pushed;
		_released  = st._released;
		_changed   = st._changed;
		_lastValue = st._lastValue;
	} //

	public void value( bool status ){
		value = (status) ? 1 : 0 ;
	} //

	public void value( int  status ){
		status = ( status > 0 ) ? 1 : 0;
		if ( _lastValue != status ) {
			_changed = true;
			if ( status > 0 ) {
				_pushed   = true;
				_released = false;
			} else {
				_pushed   = false;
				_released = true;
			}
			_lastValue = status;
		} else {
			_pushed  = false;
			_released= false;
			_changed = false;
		}
	} //

	public int value() {
		if ( _lastValue > 0 ) return 1;
		else	return 0;
	} //
} //

public class BasePad : IGamePad {
	protected ButtonStatus[] _status;
	public int x(){return 0;};
	public int y(){return 0;};
	public void x( int xx ){return 0;};
	public void y( int yy ){return 0;};
	public int xMove(){return 0;};
	public int yMove(){return 0;};

	public this(){
		this( 16 );
	} //

	public this( int num ){
		_status = new ButtonStatus[ num ];
		for ( int  i = 0 ; i < num ; i++ ) {
			_status[i] = new ButtonStatus();
		}
	} //

	protected int numc( int n ){
		if( n < 0 ) n = 0;
		else
		if( n >= _status.length ) n = _status.length-1; 
		return n;
	} //

	public int getButton( int n ){
		n = numc( n );
		return _status[ n ].value;
	} //

	public void setButton( int n  , int va ){
		n = numc( n );
		_status[ n ].value =  va ;
	} //

	public ButtonStatus[] buttonStatus(){
		return _status;
	} //

	public int  padStatus(){return 0;};
	public void padStatus( int st ){return 0;};
	public void reset(){};

} //


public class VirtualGamePad : BasePad{
	private int _x = 0 , _y = 0;
	private int _xMove , _yMove;

	public this( int num ){
		super( num );
	} //

	public this(){
		super();
	} //

	public int  x(){return _x;}
	public void x( int xx ){
		_xMove = ( _x - xx );
		_x = xx;
		return x;
	} //

	public int  y(){return _y;}
	public void y( int yy ){
		_yMove = ( _y - yy );
		_y = yy;
		return _y;
	} //
	public int xMove(){return _xMove;}
	public int yMove(){return _yMove;}

	public int padStatus(){
		return (
			((        _x + 2 )      )+
			((        _y + 2 ) <<  2 )+
			(_status[0].value  <<  4 )+
			(_status[1].value  <<  5 )+
			0
			);
	} //

	public void padStatus( int st  ){
		_x               = (   st        % 4 ) - 2;
		_y               = ( ( st >> 2 ) % 4 ) - 2;
		_status[0].value = ( ( st >> 4 ) % 2 );
		_status[1].value = ( ( st >> 5 ) % 2 );
	} //

	public void reset(){
		_x = 0; _y = 0;
		for( int i = 0 ; i < _status.length ; i++ ) _status[ i ].reset();
	} //

} //

